package cn.schoolwow.quickapi.module.ams.api.aware;

import cn.schoolwow.ams.domain.block.common.operation.OpenFieldTabBlockOperation;
import cn.schoolwow.ams.domain.block.list.clazz.ClazzListBlockConfigAware;
import cn.schoolwow.ams.domain.block.list.clazz.ClazzListBlockOption;
import cn.schoolwow.ams.domain.block.list.clazz.crud.ClazzListBlockListListener;
import cn.schoolwow.ams.domain.block.list.common.ListBlockPagingResponse;
import cn.schoolwow.ams.module.block.listBlock.common.domain.remoteSelect.BlockRemoteSelect;
import cn.schoolwow.ams.module.block.listBlock.common.domain.remoteSelect.RemoteSelectOption;
import cn.schoolwow.quickapi.domain.QuickAPIOption;
import cn.schoolwow.quickapi.module.ams.domain.QuickAPIConstant;
import cn.schoolwow.quickapi.module.business.api.domain.API;
import cn.schoolwow.quickapi.module.common.domain.APIDocument;
import cn.schoolwow.quickapi.module.initial.service.InitialQuickAPICompositeBusiness;
import cn.schoolwow.quickflow.QuickFlow;
import cn.schoolwow.util.domain.query.instanceList.QueryInstanceList;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
public class APIClazzListBlockAware extends ClazzListBlockConfigAware {
    @Autowired
    private QuickAPIOption quickAPIOption;

    @Autowired
    private QuickFlow quickAPIFlow;

    @Override
    public ClazzListBlockOption getAMSBlockConfig() {
        ClazzListBlockOption clazzListBlockOption = new ClazzListBlockOption(
                QuickAPIConstant.PROJECT_NAME, "接口", API.class);

        setShowOption(clazzListBlockOption);
        addListListener(clazzListBlockOption);
        addButton(clazzListBlockOption);
        addRemoteSelect(clazzListBlockOption);
        return clazzListBlockOption;
    }

    private void setShowOption(ClazzListBlockOption clazzListBlockOption){
        clazzListBlockOption.listBlockShowOption.simulatePaging = true;
        clazzListBlockOption.listBlockShowOption.displayFieldNames = new String[]{
                "type","description","requestMethod","url","contentType"
        };
        clazzListBlockOption.listBlockShowOption.requestFieldNames = new String[]{
                "type","description","requestMethod","url"
        };
        clazzListBlockOption.listBlockShowOption.responseFieldNames = new String[]{
                "type","description","requestMethod","url","headerMap","contentType",
                "requestBody","responseBody","parameterData","returnData","requestAndResponse"
        };
    }

    private void addListListener(ClazzListBlockOption clazzListBlockOption){
        clazzListBlockOption.clazzListBlockAPIListener.listListener = new ClazzListBlockListListener() {
            @Override
            public ListBlockPagingResponse list(JSONObject conditionMap) throws Exception {
                if(quickAPIOption.debug){
                    quickAPIFlow.executeFlow(new InitialQuickAPICompositeBusiness());
                }
                APIDocument apiDocument = quickAPIFlow.getContextInstanceData(APIDocument.class);

                List<API> filterList = new ArrayList<>();
                if(!apiDocument.apiList.isEmpty()){
                    filterList.addAll(apiDocument.apiList);
                }

                if(conditionMap.containsKey("description")){
                    String description = (String) conditionMap.get("description");
                    filterList.removeIf(api -> null==api.description||!api.description.contains(description));
                }
                if(conditionMap.containsKey("type")){
                    String type = (String) conditionMap.get("type");
                    String replaceType = type.replace(",","-");
                    filterList.removeIf(api -> !api.type.equalsIgnoreCase(replaceType));
                }
                if(conditionMap.containsKey("requestMethod")){
                    String requestMethod = (String) conditionMap.get("requestMethod");
                    filterList.removeIf(api -> !api.requestMethod.equals(requestMethod));
                }
                if(conditionMap.containsKey("url")){
                    String url = (String) conditionMap.get("url");
                    filterList.removeIf(api -> !api.url.contains(url));
                }
                return new ListBlockPagingResponse(filterList);
            }
        };
    }

    private void addButton(ClazzListBlockOption clazzListBlockOption){
        {
            OpenFieldTabBlockOperation blockOperation = new OpenFieldTabBlockOperation(
                    "请求和响应", Arrays.asList("requestAndResponse","parameterData","returnData"));
            clazzListBlockOption.blockOperationList.add(blockOperation);
        }
    }

    private void addRemoteSelect(ClazzListBlockOption clazzListBlockOption){
        {
            String[] requestMethods = new String[]{"GET","POST","PUT","DELETE"};
            List<RemoteSelectOption> remoteSelectOptionList = new ArrayList<>();
            for(String requestMethod:requestMethods){
                RemoteSelectOption remoteSelectOption = new RemoteSelectOption(requestMethod, requestMethod);
                remoteSelectOptionList.add(remoteSelectOption);
            }
            BlockRemoteSelect blockRemoteSelect = new BlockRemoteSelect("requestMethod", "请求方法", remoteSelectOptionList);
            clazzListBlockOption.remoteSelectList.add(blockRemoteSelect);
        }
        {
            List<RemoteSelectOption> remoteSelectOptionList = getTypeRemoteSelectOption();
            BlockRemoteSelect blockRemoteSelect = new BlockRemoteSelect("type", "接口类型", remoteSelectOptionList);
            blockRemoteSelect.cascade = true;
            clazzListBlockOption.remoteSelectList.add(blockRemoteSelect);
        }
    }

    private List<RemoteSelectOption> getTypeRemoteSelectOption(){
        APIDocument apiDocument = quickAPIFlow.getContextInstanceData(APIDocument.class);

        if(null==apiDocument.apiList||apiDocument.apiList.isEmpty()){
            return new ArrayList<>();
        }
        List<RemoteSelectOption> list = new ArrayList<>();

        List<String> typeList = QueryInstanceList.newQuery(apiDocument.apiList)
                .distinct()
                .execute()
                .getSingleFieldValueList("type");
        for(String type:typeList){
            String[] tokens = type.split("-", -1);
            RemoteSelectOption remoteSelectOption = null;
            for(String token:tokens){
                if(null==remoteSelectOption){
                    remoteSelectOption = QueryInstanceList.newQuery(list)
                            .addQuery("label", token)
                            .execute()
                            .getOne();
                    if(null==remoteSelectOption){
                        remoteSelectOption = new RemoteSelectOption(token, token);
                        list.add(remoteSelectOption);
                    }
                }else{
                    if(null==remoteSelectOption.children){
                        remoteSelectOption.children = new ArrayList<>();
                    }
                    RemoteSelectOption queryRemoteSelectOption = QueryInstanceList.newQuery(remoteSelectOption.children)
                            .addQuery("label", token)
                            .execute()
                            .getOne();
                    if(null==queryRemoteSelectOption){
                        RemoteSelectOption childRemoteSelectOption = new RemoteSelectOption(token, token);
                        remoteSelectOption.children.add(childRemoteSelectOption);
                        remoteSelectOption = childRemoteSelectOption;
                    }else{
                        remoteSelectOption = queryRemoteSelectOption;
                    }
                }
            }
        }
        return list;
    }
}
